<?php
declare(strict_types=1);

namespace SixShop\System;

use SixShop\Core\ExtensionAbstract;
use SixShop\Core\Service\AutoloadService;
use SixShop\System\Cron\SystemCron;
use SixShop\System\Enum\ExtensionStatusEnum;
use SixShop\System\Hook\ExtensionStatusHook;
use SixShop\System\Hook\GatheringCrontabEventHook;
use SixShop\System\Service\FrontendDeployService;
use think\db\exception\PDOException;
use think\facade\Event;

use function SixShop\Core\extension_name_list;

class Extension extends ExtensionAbstract
{

    public function __construct(private readonly AutoloadService $autoloadService)
    {
    }

    public function getHooks(): array
    {
        return [
            ExtensionStatusHook::class,
            GatheringCrontabEventHook::class
        ];
    }

    public function getCronJobs(): array
    {
        return [
            SystemCron::class
        ];
    }

    public function boot(): void
    {
        if ($this->isBooted) {
            return;
        }
        
        // 注册前端部署事件监听
        $this->registerFrontendDeployListeners();
        
        foreach (extension_name_list() as $extensionID) {
            /** @var ExtensionAbstract $extension */
            $extension = $this->autoloadService->getExtension($extensionID);
            $className = get_class($extension);
            if (method_exists($extension, 'available')
                || $className::hasMacro('available')
            ) {
                continue;
            }
            $className::macro('available', function () {
                $extensionID = $this->getInfo()['id'];
                try {
                    $info = app()->make(ExtensionManager::class)->getInfo($extensionID);
                } catch (PDOException) {
                    // 新装系统的时候system扩展还未安装
                    return false;
                }
                return $info->status === ExtensionStatusEnum::ENABLED;
            });

        }
        parent::boot();
    }
    
    /**
     * 注册前端部署事件监听器
     */
    private function registerFrontendDeployListeners(): void
    {
        // 监听安装后事件
        Event::listen('after_install_extension', function (string $extensionId) {
            try {
                $service = app(FrontendDeployService::class);
                $service->deploy($extensionId);
            } catch (\Exception $e) {
                // 记录错误但不影响安装流程
                \think\facade\Log::error("前端部署失败：{$extensionId}，错误：" . $e->getMessage());
            }
        });
        
        // 监听卸载前事件
        Event::listen('before_uninstall_extension', function (string $extensionId) {
            try {
                $service = app(FrontendDeployService::class);
                $service->remove($extensionId);
            } catch (\Exception $e) {
                // 记录错误但不影响卸载流程
                \think\facade\Log::error("前端清理失败：{$extensionId}，错误：" . $e->getMessage());
            }
        });
    }

    public  function available()
    {
        return true;
    }

    protected function getBaseDir(): string
    {
        return dirname(__DIR__);
    }
}